import json
from urllib.parse import parse_qs

from channels.generic.websocket import AsyncWebsocketConsumer

from llm.entity.dto.DeviceCtlDTO import DeviceCtlDTO
from llm.service.DeviceService import DeviceService
from llm.service.OpenAIService import OpenAIRunService
from HomeAutoAI.common.Results import WebSocketResult
from llm.workflows import half_output
from llm.workflows.half_output import output_invoke, output_invoke_stream, mark_message


class CommandParserConsumer(AsyncWebsocketConsumer):
    """
    流程:发送指令->解析指令->发送指令到OpenAI->执行方法调用->返回结果（使用两个Assistant两个run完成）
    """

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.thread_id = None  # 准备好变量
        self.assistant_parser_id = None

    async def connect(self):
        # # 解析query_string中的参数,这里因为一个会话对应一个thread，所以thead_id从query_string中获取
        # query_string = self.scope['query_string'].decode()
        # query_params = parse_qs(query_string)
        # self.thread_id = query_params.get('thread_id', [''])[0]
        # print(f'连接中，获得会话thread-id: {self.thread_id}')
        print(f'CommandParserConsumer 连接成功！')
        await self.accept()

    async def disconnect(self, code):
        print(f'CommandParserConsumer 断开连接！')
        await self.close()

    async def receive(self, text_data=None, bytes_data=None):
        """
        接收到消息后，转发给对应的函数处理
        :param text_data:
        :param bytes_data:
        :return:
        """

        print(f'CommandParserConsumer 接收到消息：{text_data}')
        if json.loads(text_data).get('type') == 'ping':
            print(f'CommandParserConsumer 接收到ping消息')
            await self.send(WebSocketResult.pong())
        else:
            command = self.load_params(text_data)
            parsed_command = await OpenAIRunService.aparse_command(
                thread_id=self.thread_id,
                message=command,
                assistant_id=self.assistant_parser_id,
            )
            if parsed_command is not None or parsed_command != '':
                for command in json.loads(parsed_command):
                    dto = DeviceCtlDTO.from_json(command)
                    DeviceService.oneNET_device_control(dto)
                # half_output = await output_invoke(parsed_command, thread_id=self.thread_id)
                run = await output_invoke_stream(parsed_command, thread_id=self.thread_id, consumer=self)
                await mark_message(thread_id=self.thread_id, run=run)
                # await self.send(text_data=WebSocketResult.success(message="解析成功", data=json.dumps(parsed_command)))
                await self.send(text_data=WebSocketResult.success(message="解析成功", data={"isStreamEnd": True}))

            print(f'CommandParserConsumer 接受消息处理完成！')

    def load_params(self, text_data) -> str:
        """
        解析消息中的参数，并加载到self中的参数中
        :param text_data:
        :return:
        """
        data = json.loads(text_data)
        command = data.get('command_message')
        self.assistant_parser_id = data.get('assistant_id')
        print(f'CommandParserConsumer 接收到命令：{command}')
        self.thread_id = data.get('thread_id')
        return command
